package com.hzbc.faceattendance.exception;

import com.hzbc.faceattendance.dto.ApiResponse;
import io.jsonwebtoken.*;
import jakarta.persistence.EntityNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.NoHandlerFoundException;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(NoHandlerFoundException ex) {
        log.error("资源未找到: {}", ex.getRequestURL());
        return new ResponseEntity<>(
                new ErrorResponse("NOT_FOUND", "请求资源不存在"),
                HttpStatus.NOT_FOUND
        );
    }

    @ExceptionHandler(UsernameNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(UsernameNotFoundException ex) {
        log.warn("用户不存在: {}", ex.getMessage());
        return new ResponseEntity<>(
                new ErrorResponse("USER_NOT_FOUND", "用户不存在"),
                HttpStatus.NOT_FOUND
        );
    }

    @ExceptionHandler(BadCredentialsException.class)
    public ResponseEntity<ErrorResponse> handleInvalidPassword(BadCredentialsException ex) {
        log.warn("认证失败: 用户名或密码错误");
        return new ResponseEntity<>(
                new ErrorResponse("INVALID_CREDENTIALS", "用户名或密码错误"),
                HttpStatus.UNAUTHORIZED
        );
    }

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<ErrorResponse> handleAccessDenied(AccessDeniedException ex) {
        log.warn("访问拒绝: {}", ex.getMessage());
        return new ResponseEntity<>(
                new ErrorResponse("ACCESS_DENIED", "无访问权限"),
                HttpStatus.FORBIDDEN
        );
    }

    @ExceptionHandler({EmptyResultDataAccessException.class, EntityNotFoundException.class})
    public ResponseEntity<ErrorResponse> handleDataNotFound(RuntimeException ex) {
        log.error("数据不存在: {}", ex.getMessage());
        return new ResponseEntity<>(
                new ErrorResponse("DATA_NOT_FOUND", "资源不存在"),
                HttpStatus.NOT_FOUND
        );
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
        String errorMsg = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        log.warn("参数校验失败: {}", errorMsg);
        return new ResponseEntity<>(
                new ErrorResponse("VALIDATION_FAILED", errorMsg),
                HttpStatus.BAD_REQUEST
        );
    }

    @ExceptionHandler({
            ExpiredJwtException.class,
            SignatureException.class,
            MalformedJwtException.class,
            UnsupportedJwtException.class,
            IllegalArgumentException.class
    })
    public ResponseEntity<ErrorResponse> handleJwtExceptions(Exception ex) {
        String errorType = "INVALID_TOKEN";
        if (ex instanceof ExpiredJwtException) {
            errorType = "TOKEN_EXPIRED";
            log.warn("JWT令牌过期: {}", ex.getMessage());
        } else {
            log.warn("无效的JWT令牌: {}", ex.getMessage());
        }
        return new ResponseEntity<>(
                new ErrorResponse(errorType, ex.getMessage()),
                HttpStatus.UNAUTHORIZED
        );
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<?>> handleAllExceptions(Exception ex) {
        HttpStatus status = determineHttpStatus(ex);
        log.error("系统异常: ", ex);
        return new ResponseEntity<>(
                new ApiResponse<>(false, status.value(), ex.getMessage(), null),
                status
        );
    }

    private HttpStatus determineHttpStatus(Exception ex) {
        if (ex instanceof AuthenticationException) {
            return HttpStatus.UNAUTHORIZED;
        }
        if (ex instanceof AccessDeniedException) {
            return HttpStatus.FORBIDDEN;
        }
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }

    // 错误响应内部类
    private static class ErrorResponse {
        private final String code;
        private final String message;

        public ErrorResponse(String code, String message) {
            this.code = code;
            this.message = message;
        }

        // Getter 方法
        public String getCode() { return code; }
        public String getMessage() { return message; }
    }
}